#include "timer.h"

namespace sylar{
    bool Timer::cancel(){
        //取消有效任务定时器: 先将回调函数置为空(如果有)，再从set中删除
        std::unique_lock<std::shared_mutex> lock(_manager->_mtx); //写互斥锁

        if(_func == nullptr){
            return false; 
        }else{
            _func = nullptr;
        }
        auto it = _manager->_timers.find(shared_from_this());
        if(it != _manager->_timers.end()){
            _manager->_timers.erase(it);
        }
        return true;
    }
    bool Timer::refresh(){
        //刷新有效定时器：先查找，再删除，再更新，再插入
        if(_func == nullptr) return false;

        auto it = _manager->_timers.find(shared_from_this());
        if(it == _manager->_timers.end()){
            return false;
        }
        _manager->_timers.erase(it);
        _clock = std::chrono::system_clock::now()+std::chrono::milliseconds(_ms);
        _manager->_timers.insert(shared_from_this());
        return true;
    }
    bool Timer::reset(uint64_t ms,bool from_now){
        //from_now为true时从now开始计算超时时间，为false时从上次开始计算超时时间开始计算超时时间
        if(ms == _ms && !from_now){
            return true; // 无需更改
        }
        if(_func == nullptr) return false;

        {
            std::unique_lock<std::shared_mutex> lock(_manager->_mtx);
            auto it = _manager->_timers.find(shared_from_this());
            if(it == _manager->_timers.end()) return false;
            _manager->_timers.erase(it);

            auto start = from_now ? std::chrono::system_clock::now() : _clock-std::chrono::milliseconds(_ms);
            _clock = start + std::chrono::milliseconds(ms);
            _ms = ms;

            _manager->_timers.insert(shared_from_this());
        }
        return true;
    }
    Timer::Timer(uint64_t ms,func_t func,bool is_recurring,TimerManager* manager)
        :_ms(ms),_func(func),_is_recurring(is_recurring),_manager(manager)
    {
        _clock = std::chrono::system_clock::now()+std::chrono::milliseconds(_ms);
    }
    bool Timer::Compare::operator()(const std::shared_ptr<Timer>& t1,const std::shared_ptr<Timer>& t2) const{
        assert(t1!=nullptr && t2!=nullptr);
        return t1->_clock < t2->_clock;
    }

    TimerManager::TimerManager(){
        _lastclock = std::chrono::system_clock::now();//初始化，用于后续检查系统时间是否回退
    }
    TimerManager::~TimerManager(){

    }
    std::shared_ptr<Timer> TimerManager::addTimer(uint64_t ms,func_t func,bool is_recurring){
        std::shared_ptr<Timer> timer(new Timer(ms,func,is_recurring,this));
        addTimer(timer);
        return timer;
    }
    void TimerManager::addTimer(std::shared_ptr<Timer> timer){
        bool at_front = false;//用于标识是否插入的是首部
        {
            std::unique_lock<std::shared_mutex> lock(_mtx);
            auto it = _timers.insert(timer).first;
            at_front = (it == _timers.begin())&&!_tickled;
            if(at_front) _tickled = true;
        }
        if(at_front){
            onTimerInsertAtFront();//执行更新最近一次时间
        }
    }

    static void OnTimer(std::weak_ptr<void> weak_condition,func_t func){
        std::shared_ptr<void> cd = weak_condition.lock();
        if(cd){
            //如果弱指针的引用任然存在则执行
            func();
        }
    }

    std::shared_ptr<Timer> TimerManager::addCondTimer(uint64_t ms,func_t func,std::weak_ptr<void> weak_condition,bool is_recurring){
        return addTimer(ms,std::bind(&OnTimer,weak_condition,func),is_recurring);
    }

    uint64_t TimerManager::getNextTimer(){
        std::shared_lock<std::shared_mutex> lock(_mtx);
        //要重置tickled
        _tickled = false;
        //如果——timers为空
        if(_timers.empty()){
            return ~0ull;
        }
        //如果已经超时返回0
        auto locktime = (*_timers.begin())->_clock;
        auto now = std::chrono::system_clock::now();
        if(now >= locktime){
            return 0;
        }

        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(locktime-now);
        return static_cast<uint64_t>(duration.count());

        //正常情况返回
    }
    bool TimerManager::hasTimer(){
        std::unique_lock<std::shared_mutex> lock(_mtx);
        return !_timers.empty();
    }
    bool TimerManager::detectClockRollover(){
        bool rollover = false;
        auto now = std::chrono::system_clock::now();
        
        if(now < (_lastclock-std::chrono::milliseconds(60*60*1000))){
            //当现在的时间比之前的时间还早，那么肯定发生了严重的时间回滚
            rollover = true;
        }
        _lastclock = now;
        return rollover;
    }

    void TimerManager::getExpiredfunc(std::vector<func_t>& func_v){
        auto now = std::chrono::system_clock::now();

        std::unique_lock<std::shared_mutex> lock(_mtx);
        bool rollover = detectClockRollover();

        while(!_timers.empty() && (rollover || (*_timers.begin())->_clock <= now)){
            //任务列表不为空，且 发生时间回滚或者首定时任务过期则需要取出
            //取出-》删除-》将定时器任务加入func_v-》判断是否循环timer还要不要加入——timers
            std::shared_ptr<Timer> timer = (*_timers.begin());
            _timers.erase(_timers.begin());
            func_v.push_back(timer->_func);

            if(timer->_is_recurring){
                timer->_clock = now+std::chrono::milliseconds(timer->_ms);
                _timers.insert(timer);
            }else{
                timer->_func = nullptr;//注销回调函数
            }
        }
    }
}